package LeetDev.a3d;

public class DecomposedAnim extends Anim{

	private int m_parentNode;
	private int m_frames;
	private int m_fps;
	
	private byte m_types[]=new byte[10];
	private float m_values[][]=new float[10][];
	
	private boolean m_isStatic;

	// We only do animations single threaded, so we save a lot of memory by having these members static.
	private static Matrix m_tmpAnimMatrix=new Matrix();
	private static Quat m_tmpAnimQuat=new Quat();
	private static float v[]=new float[4];
	private static float c[][]=new float[4][10];
	private static Matrix m[]={new Matrix(),new Matrix(),new Matrix(),new Matrix()};
	
	void polynomials(float time,float[] v)
	{
		v[0]=1-time;
		v[2]=time*3*v[0];
		v[1]=v[0]*v[2];
		v[2]*=time;
		v[0]*=v[0]*v[0];
		v[3]=time*time*time;
	}

	public DecomposedAnim(FileInput fin,final String name,int frames,int fps,int parentnode) throws Exception
	{
		super(name);
		m_frames=frames;
		m_fps=fps;
		m_parentNode=parentnode;
		m_isStatic=true;
		int t;
		for(t=0;t<10;t++)
		{
			m_types[t]=0;
		}
		for(t=0;t<10;t++)
		{
			m_types[t]=fin.popByte();
			if(m_types[t]==0)
			{
				m_values[t]=new float[1];
			}
			else
			{
				m_values[t]=new float[frames];
				m_isStatic=false;
			}
			for(int i=0;i<m_values[t].length;++i)
			{
				m_values[t][i]=fin.popFloat();
			}
		}
	}

	public void use(double ticks, double delta,Matrix[] matrixlist,final int nodenum)
	{
		int t,i,j;
		if(m_isStatic)
		{
			m_tmpAnimQuat.w=m_values[3][0];
			m_tmpAnimQuat.x=m_values[0][0];
			m_tmpAnimQuat.y=m_values[1][0];
			m_tmpAnimQuat.z=m_values[2][0];
			m_tmpAnimMatrix.set(m_tmpAnimQuat);
			m_tmpAnimMatrix.scale(m_values[4][0],m_values[5][0],m_values[6][0]);
			m_tmpAnimMatrix.m[12]=m_values[7][0];m_tmpAnimMatrix.m[13]=m_values[8][0];m_tmpAnimMatrix.m[14]=m_values[9][0];
		}
		else
		{
			m_time+=(delta*m_speed);
			float modulus=(float)(m_time*(double)m_fps);
			int frame=((int)modulus)%m_frames;
			modulus-=(float)((int)modulus);
			if(frame<0) {frame+=m_frames;}
			if(m_time<0) {modulus+=1;}
	
			float a,b;
			polynomials(modulus,v);
			for(t=0;t<10;t++)
			{
				if(m_types[t]==0)
				{
					c[0][t]=c[1][t]=c[2][t]=c[3][t]=m_values[t][0];
				}
				else
				{
					c[0][t]=m_values[t][frame];
					c[1][t]=m_values[t][(frame+1)%m_frames];
					c[2][t]=m_values[t][(frame+2)%m_frames];
					c[3][t]=m_values[t][(frame+m_frames-1)%m_frames];
				}
			}
			for(t=0;t<4;t++)
			{
				m_tmpAnimQuat.w=c[t][3];
				m_tmpAnimQuat.x=c[t][0];
				m_tmpAnimQuat.y=c[t][1];
				m_tmpAnimQuat.z=c[t][2];
				m[t].set(m_tmpAnimQuat);
				m[t].scale(c[t][4],c[t][5],c[t][6]);
				m[t].m[12]=c[t][7];m[t].m[13]=c[t][8];m[t].m[14]=c[t][9];
				
			}
			// Lazy done... Could be better with quaternion slerp and such... But it is fast and good enough.
			for(j=0;j<16;j+=4)
			{
				for(i=0;i<3;i++)
				{
					a=((m[1].m[j+i]-m[3].m[j+i])*0.166f)+m[0].m[j+i];
					b=((m[0].m[j+i]-m[2].m[j+i])*0.166f)+m[1].m[j+i];
					m_tmpAnimMatrix.m[j+i]=(m[0].m[j+i]*v[0])+(m[1].m[j+i]*v[3])+(a*v[1])+(b*v[2]);
				}
			}
		}
		m_tmpAnimMatrix.m[3]=0;
		m_tmpAnimMatrix.m[7]=0;
		m_tmpAnimMatrix.m[11]=0;
		m_tmpAnimMatrix.m[15]=1;
		m_tmpAnimMatrix.special_mul(matrixlist[m_parentNode],matrixlist[nodenum]);
		
	}
}
